#include<vector>
#include<iostream>
#include<cstdlib>
#include<cstring>

class MyString {
    private:
        char* data;
        size_t   len;
        void copyData(const char *s) {
            data = new char[len+1];
            memcpy(data, s, len);
            data[len] = '\0';
        }
    public:
        MyString() {
            data = NULL;
            len = 0;
            std::cout << "default constructor " << " this:" << this << std::endl;
        }

        MyString(const char* p) {
            len = strlen (p);
            copyData(p);
            std::cout << "const char * constructor" << " this:" << this << std::endl;
        }

        // can replaced with MyString( MyString && str) ==> right value ref
        // function call 时调用 copy constructor
        // caller:  
        //  f( 右值引用)  
        //  f(左值引用) 都可以; 
        // callee: 
        //    缺点 函数体里面，只能使用str的const 方法
        //
        // 解决了该缺点 就使用  MyString(MyString && str)  
        //      => caller 必须是  MyString("hello") 或者 MyString(MyString("hello"));
        MyString(const MyString& str) {
            len = str.len;
            copyData(str.data);
            std::cout << "Copy Constructor is called! source: " << str.data << " this:" << this << std::endl;
        }
//        MyString(MyString && str){
//            len = str.len;
//            data = str.data;
//            std::cout << "Copy constructor with &&" << " this:" << this << std::endl;
//        }

        MyString& operator=(const MyString& str) {
            if (this != &str) {
                len = str.len;
                copyData(str.data);
            }
            std::cout << "Copy Assignment is called! source: " << str.data <<  " this:" << this << std::endl;
            return *this;
        }



        virtual ~MyString() {
            if (data){
                std::cout << "destructor, source:" << data << " this:" << this << std::endl;
                free(data);
                data = nullptr;
            }
        }

        void show(){
            std::cout << "data:" << data << " len:" << len << std::endl;
        }
        void show() const {
            std::cout << "const show : data:" << data << " len:" << len << std::endl;
        }
};



void testMyString(){
    {
        MyString a;
        a = MyString("Hello"); // const char * constructor && operator=
    }

    std::cout << "\nnext step vec.push_back(MyString(\"World\")); " << std::endl;
    {
        std::vector<MyString> vec;
        vec.push_back(MyString("World")); // const char * constructor && copy constructor
        vec.front().show();
    }

    std::cout << "\nnext step vec.push_back(mystr); " << std::endl;
    {
        MyString a = "chenglun";
        std::vector<MyString> vec;
        vec.push_back(a); // const char * constructor && copy constructor
        vec.front().show();
    }

    std::cout << "\nnext step f(&&) f(&); " << std::endl;
    {
        auto rref = [](MyString && str) {
            str.show();
        };
        
        rref("hello");
        rref(MyString("hello"));
        // Complie Error:  
        //  MyString a = "hello";
        //  rref(a); 
        
        auto lref = [](MyString & str){
            str.show();
        };
        MyString a = "hellowld";
        lref(a); 
    }
}

int main(){
    testMyString();
    return 0;
}




